Skip to content

docs: rebuild the v2 documentation around a task-based page tree#2397

Merged
felixweinberger merged 27 commits into
mainfrom
fweinberger/docs-content
Jun 30, 2026
Merged

docs: rebuild the v2 documentation around a task-based page tree#2397
felixweinberger merged 27 commits into
mainfrom
fweinberger/docs-content

Conversation

@felixweinberger

Copy link
Copy Markdown
Contributor

Rebuilds the v2 documentation content on the VitePress site introduced in #2395. The two ~1,000-line guides, the two quickstarts, and the FAQ are replaced by a task-based page tree — get started, servers, serving, clients, protocol versions, advanced, testing, troubleshooting — with one job per page. Every code block on every page is included from a typecheck-gated companion example, the runnable companions are executed in CI, and the quoted outputs on the pages are the outputs those programs produce.

Motivation and Context

#2395 replaced the typedoc site with a real documentation site but deliberately kept the existing content. This is the content half: pages organized around what the reader is doing instead of two monolithic guides, written code-first, with the API reference staying a generated section rather than the site.

The migration guides are carried over with only link retargeting.

How Has This Been Tested?

  • Every ts fence is a //#region of a companion file under examples/guides/; the examples workspace typechecks them against the SDK, and pnpm sync:snippets --check fails if a page drifts from its source region.
  • New pnpm docs:examples step (wired into the examples CI job) executes every runnable companion — 37 programs, 6 typecheck-only — so behavior shown on a page is exercised on every PR, not just compiled. Quoted outputs on the pages are taken from those runs.
  • pnpm docs:build passes with dead-link checking enabled: 0 dead links, 0 typedoc warnings, 191 pages.
  • Each page's API claims (symbols, signatures, options, import specifiers) were verified against the package sources, and the example programs were re-run, in a final review pass before this PR.
  • pnpm --filter @modelcontextprotocol/server test passes (one error-message string changed).

Breaking Changes

None at runtime. Five documentation URLs are removed in favor of the new tree (/v2/server, /v2/client, /v2/server-quickstart, /v2/client-quickstart, /v2/faq), without redirects. Inbound references (README, package READMEs, migration guides, examples README, one error-message URL in @modelcontextprotocol/server) are repointed.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

  • The README's v2 status banner is rewritten for the beta with a feedback call to action, backed by a new v2-labeled issue form (.github/ISSUE_TEMPLATE/v2-feedback.yml); a small Examples page in Get started links the example library.
  • The doc column is widened (the default theme caps it at 688px, which forced horizontal scrolling on typical snippets).
  • The landing page is now a real page (orientation, a complete server, and entry points) rather than the rendered README, so the README-landing generator from docs: replace the typedoc site with VitePress (v2 + v1 reface) #2395 is removed again in favor of plain content.
  • Sunset surfaces (sampling, roots) carry deprecation banners with their migration targets first; era differences live on one page (protocol-versions) that everything else links to.
  • The legacy guide snippet collections under examples/guides/{server,client}Guide.examples.ts are deleted with the pages they fed; the runnable example stories under examples/<story>/ are untouched.

Lay out the 45-page docs-v2 tree: authoring conventions in _meta/CONVENTIONS.md,
a one-line-per-page index in _TREE.md, H2-outline scaffolds for 39 pages, and
byte-identical copies of the three migration guides.
Fully write index, get-started/first-server, and servers/tools. Their code
fences are region-synced from new examples/guides companion files that
typecheck in the examples workspace.
Moves the docs-v2 scaffold into docs/ proper, wires the 45-page sidebar,
keeps the existing guide pages under a collapsed 'Current guides (being
replaced)' group, and replaces the README-generated landing with the
calibration index. Dead-link checking is suspended on this branch only
while most pages are scaffolds.
- sessions-state-scaling: rename the three H2s to imperative micro-steps
  (Pin a client to a session / Resume a dropped stream / Scale across nodes)
  so the page matches the rest of the serving how-to recipes
- legacy-clients: rewrite the serveStdio 'reject' sentence in active voice
- web-standard: stop telling the reader to export the guarded handler as the
  default; the 'Run it and verify' step curls the default export from
  127.0.0.1, which the Host allowlist would 403, contradicting the quoted
  output
Remove docs/server.md, docs/client.md, docs/server-quickstart.md,
docs/client-quickstart.md, and docs/faq.md now that the page tree under
docs/get-started, docs/servers, docs/serving, docs/clients,
docs/protocol-versions.md, and docs/troubleshooting.md replaces them, and
drop the "Current guides (being replaced)" sidebar group.

Repoint every inbound reference:

- README.md: the Getting Started bullets now point at
  docs/get-started/first-server.md and first-client.md, and the
  Documentation section links the tutorials, the documentation site, and
  docs/troubleshooting.md in place of the Server Guide / Client Guide /
  FAQ bullets.
- packages/server/README.md and packages/client/README.md (embedded into
  the typedoc API pages) link to the published site instead of the
  deleted GitHub pages.
- packages/server/src/server/requestStateCodec.ts: the Web Crypto error
  message now points at the troubleshooting page (which carries the
  Node.js polyfill entry) instead of docs/faq.md.
- docs/migration/{index,upgrade-to-v2,support-2026-07-28}.md: replace the
  faq.md / server.md / client.md links with their live equivalents.
- examples/README.md, examples/guides/README.md, the quickstart story
  READMEs, and examples/oauth-client-credentials/README.md describe and
  link the live pages.
- docs/_meta/CONVENTIONS.md: the illustrative scaffold comment and the
  live sync-checked fence reference live files.

Also remove examples/guides/serverGuide.examples.ts and
clientGuide.examples.ts: their only consumers were the deleted guide
pages.
The README's status block now says beta, asks for feedback through a new
v2-labeled issue form, and points the doc links at the documentation site.
The PR-restriction warning is reworded without the stale date.
…nt rules

The guide companions are documentation snippets: filenames mirror their page
slugs and every region must stay self-contained when rendered, so the
example-app style rules do not apply to them. Formatting the files re-syncs
the doc fences that mirror their regions.
@felixweinberger felixweinberger requested a review from a team as a code owner June 30, 2026 17:19
@changeset-bot

changeset-bot Bot commented Jun 30, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 4aa9554

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jun 30, 2026

Copy link
Copy Markdown

Open in StackBlitz

@modelcontextprotocol/client

npm i https://pkg.pr.new/@modelcontextprotocol/client@2397

@modelcontextprotocol/codemod

npm i https://pkg.pr.new/@modelcontextprotocol/codemod@2397

@modelcontextprotocol/core

npm i https://pkg.pr.new/@modelcontextprotocol/core@2397

@modelcontextprotocol/server

npm i https://pkg.pr.new/@modelcontextprotocol/server@2397

@modelcontextprotocol/server-legacy

npm i https://pkg.pr.new/@modelcontextprotocol/server-legacy@2397

@modelcontextprotocol/express

npm i https://pkg.pr.new/@modelcontextprotocol/express@2397

@modelcontextprotocol/fastify

npm i https://pkg.pr.new/@modelcontextprotocol/fastify@2397

@modelcontextprotocol/hono

npm i https://pkg.pr.new/@modelcontextprotocol/hono@2397

@modelcontextprotocol/node

npm i https://pkg.pr.new/@modelcontextprotocol/node@2397

commit: 4aa9554

Comment thread examples/guides/clients/subscriptions.examples.ts Dismissed
Comment thread examples/guides/serving/authorization.examples.ts Dismissed
Comment thread examples/guides/serving/express.examples.ts Dismissed
Comment thread examples/guides/serving/fastify.examples.ts Dismissed
Comment thread examples/guides/get-started/firstClient.examples.ts Outdated
Comment thread docs/index.md Outdated
CI typechecks the workspace without building the packages first, so the
examples package resolves @modelcontextprotocol/* imports through its
tsconfig paths; the validator subpaths used by the schema-libraries guide
companion were missing from that map and only resolved locally via built
dists.
Comment thread examples/guides/serving/sessions-state-scaling.examples.ts
Comment thread docs/_meta/_TREE.md Outdated
…ession

The sessions routing example returned 404 for both an unknown
Mcp-Session-Id and a request that lacked the header entirely; the latter is
a malformed request and gets 400, matching examples/legacy-routing.
The guide companions and the contributor conventions still referenced the
docs-v2/ working directory the pages were drafted in; the page tree index
duplicated (and already contradicted) the sidebar, so it is removed; the
root CLAUDE.md entry for examples/guides described the retired snippet
collections.
@felixweinberger felixweinberger merged commit b153505 into main Jun 30, 2026
19 checks passed
@felixweinberger felixweinberger deleted the fweinberger/docs-content branch June 30, 2026 20:18
Comment thread docs/index.md
Comment on lines +1 to +4
---
status: calibration
shape: landing
---

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Three published pages — docs/index.md, docs/get-started/first-server.md, and docs/servers/tools.md — still carry the internal drafting-pipeline frontmatter key status: calibration (defined only in docs/_meta/CONVENTIONS.md as a writing-workflow marker); no other shipped page has a status: key. VitePress ignores unknown frontmatter, so nothing breaks, but it is internal-process metadata in public page sources — drop the status: calibration line from all three pages, keeping the shared shape: key.

Extended reasoning...

What it is. grep '^status:' docs/**/*.md matches exactly three files in the tree this PR ships: docs/index.md:2, docs/get-started/first-server.md:2, and docs/servers/tools.md:2, each carrying status: calibration in its frontmatter. No other published page has a status: key, while the shape: key (also in those frontmatter blocks) is shared by every page in the tree.

Where the key comes from. docs/_meta/CONVENTIONS.md, added in this same PR, defines status: as a drafting-pipeline marker: scaffold pages get status: scaffold, and the calibration pages were the Felix-approved samples used to calibrate the writing register ("every non-calibration page is a SKELETON"). It is a writing-workflow state field, not a documented or rendered VitePress frontmatter field. _meta/ itself is excluded from the published site via srcExclude, but these three pages are not — they are the landing page, the first tutorial, and the Tools page, the most-visited pages in the new tree.

Why nothing catches it. VitePress silently ignores unknown frontmatter keys, so pnpm docs:build passes and the rendered pages look identical with or without the line. Only someone reading the page sources (or a contributor copying a page's frontmatter as a template for a new page) sees it.

Why it matters anyway. This is exactly the class of drafting residue the PR's own final commit ("docs: scrub stale drafting references from the companions and meta docs") removed elsewhere, so the three remaining status: calibration lines contradict that cleanup and the rest of the tree's frontmatter convention. A contributor who copies one of these pages as a starting point would propagate an internal-process key with no meaning outside the drafting workflow.

Step-by-step proof. (1) Run grep -rn '^status:' docs --include='*.md' at the head commit — it returns only the three files above. (2) Open docs/_meta/CONVENTIONS.md and find the SCAFFOLD FORMAT block: the frontmatter template is status: scaffold / shape: <…>, confirming status: is a drafting-state field. (3) Open any other shipped page (e.g. docs/servers/resources.md) — its frontmatter has only shape:. (4) Build the site: VitePress renders all three pages identically whether the line is present or not, confirming the key is dead metadata.

Fix. Delete the status: calibration line from the frontmatter of docs/index.md, docs/get-started/first-server.md, and docs/servers/tools.md, keeping the shape: key each page shares with the rest of the tree. No other change is needed; this should not block the merge.

Comment thread docs/_meta/CONVENTIONS.md
Comment on lines +232 to +233
NEVER run bare `pnpm sync:snippets` — it rewrites every fenced block in `docs/` and
`docs/` in place, and concurrent mutating runs from parallel agents race and clobber

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Lines 232-233 read "it rewrites every fenced block in docs/ and docs/ in place" — the same directory is named twice, a leftover from the mechanical docs-v2/ → docs/ replacement (the original sentence enumerated docs/ and docs-v2/). Drop the duplicate so it reads "every fenced block in docs/ in place".

Extended reasoning...

What it is. docs/_meta/CONVENTIONS.md lines 232-233, in section "5. The sync command (HARD RULE)", currently read: "NEVER run bare pnpm sync:snippets — it rewrites every fenced block in docs/ and docs/ in place, and concurrent mutating runs from parallel agents race and clobber each other." The sentence names the same directory twice in one breath.

Where it came from. The earlier review round flagged stale docs-v2/ path references throughout this file and the companion-file headers. The final commit (docs: scrub stale drafting references from the companions and meta docs, 4aa9554) fixed those by mechanically replacing docs-v2/ with docs/ — and this sentence originally enumerated two distinct trees ("in docs/ and docs-v2/"), so the replacement collapsed it into the duplicated phrase. The file now contains zero docs-v2 occurrences, confirming the substitution; this duplication is the one artifact the scrub left behind, and it is not covered by the existing claude[bot] comment (which described the pre-scrub state, since fixed).

The code path / where readers hit it. CONVENTIONS.md presents itself as the "Single source of truth for form" that "every writer agent reads … before touching a page," and this particular sentence is a HARD RULE about which command contributors must never run. A garbled rule sentence in the contributors' source-of-truth document is exactly the kind of prose-vs-reality drift the rest of this PR takes care to avoid.

Why nothing catches it. docs/_meta/** is in srcExclude in docs/.vitepress/config.mts, so the file never reaches the published site and no build, link check, or snippet check looks at its prose. Only a human reading the conventions notices.

Step-by-step proof. (1) Open docs/_meta/CONVENTIONS.md at the head commit and go to section 5. (2) Line 232-233 reads "…rewrites every fenced block in docs/ and docs/ in place…". (3) grep -c docs-v2 docs/_meta/CONVENTIONS.md returns 0, so the second docs/ cannot be referring to a second tree — it is the residue of docs-v2/ after the find/replace. (4) The sync script (scripts/sync-snippets.ts) scans only docs/**/*.md, so the corrected sentence should name a single tree.

Impact and fix. No reader-facing or runtime impact — purely contributor-facing prose — hence nit. The fix is a one-phrase edit: change the sentence to "it rewrites every fenced block in docs/ in place, and concurrent mutating runs from parallel agents race and clobber each other."

Comment thread packages/client/README.md
- **[Repository README](https://github.com/modelcontextprotocol/typescript-sdk#readme)** — overview, package layout, examples
- **[Client guide](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/docs/client.md)**
- **[Client guide](https://ts.sdk.modelcontextprotocol.io/v2/clients/connect)** — connecting, calling tools, OAuth, and middleware
- **[API reference](https://ts.sdk.modelcontextprotocol.io/v2/)**

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 The 'API reference' bullets in packages/client/README.md:25 and packages/server/README.md:29 still link to https://ts.sdk.modelcontextprotocol.io/v2/, which after this PR is the hand-written docs landing page rather than the typedoc reference. Both should point at https://ts.sdk.modelcontextprotocol.io/v2/api/, matching the root README updated in this same PR and the docs/index.md fix in a401b35.

Extended reasoning...

What the bug is. Both package READMEs end with a small link list, and in each one the bullet labeled API reference points at https://ts.sdk.modelcontextprotocol.io/v2/ (packages/client/README.md:25, packages/server/README.md:29). Before this PR, /v2/ was the README-rendered landing of the docs site, so the label was loosely accurate. After this PR, /v2/ is the new hand-written content landing page (docs/index.md, added here), and the typedoc-generated API reference lives one level deeper at /v2/api/ — see the nav entry { text: 'API Reference', link: '/api/' } in docs/.vitepress/config.mts combined with base: '/v2/'.

Why it is in scope for this PR. Both files are touched by this diff: the Client guide / Server guide bullets directly above these lines are repointed to the new page tree. The PR also updates the root README.md to link API reference correctly to https://ts.sdk.modelcontextprotocol.io/v2/api/ (README.md:147), and the head commit a401b35 fixed the identical mistake on docs/index.md (now ./api/). The two package README bullets are the only remaining API reference labels that still point at the landing page, so the inconsistency is introduced/left behind by this PR's redefinition of what /v2/ is.

Impact. These READMEs are what npm renders for @modelcontextprotocol/client and @modelcontextprotocol/server. A user who clicks API reference lands on the docs home instead of the generated reference and has to find the API Reference nav entry themselves. No runtime impact, and pnpm docs:build's dead-link check cannot catch it because the URL is an absolute external URL that does resolve — just to the wrong page.

Step-by-step proof. (1) Open packages/client/README.md:25: the href is https://ts.sdk.modelcontextprotocol.io/v2/. (2) With base: '/v2/' in docs/.vitepress/config.mts, that URL renders docs/index.md — the landing page added by this PR — not the typedoc output. (3) The reference itself is published at /v2/api/, which is exactly where the root README's API reference bullet (updated in this same diff) and the fixed docs/index.md link now point. (4) So the package README link's label and target disagree, while every other API reference link in the repo agrees on /v2/api/.

Fix. Change the URL in both bullets to https://ts.sdk.modelcontextprotocol.io/v2/api/:

- **[API reference](https://ts.sdk.modelcontextprotocol.io/v2/api/)**

One-line change in each of packages/client/README.md and packages/server/README.md.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants